/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-04
 * V4.0
 */
package com.jphenix.driver.log;

import java.io.InputStream;
import java.util.List;

import com.jphenix.driver.log.systemouta.SystemOutLog;
import com.jphenix.driver.log.util.NullLogShadow;
import com.jphenix.driver.log.xlogc.XLog;
import com.jphenix.driver.log.xlogc.XLogFilter;
import com.jphenix.driver.nodehandler.FNodeHandler;
import com.jphenix.driver.propertie.instanceb.XmlConfProp;
import com.jphenix.kernel.objectloader.interfaceclass.IBeanFactory;
import com.jphenix.share.lang.SBoolean;
import com.jphenix.share.util.SFilesUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.log.ILog;
import com.jphenix.standard.log.ILogShadow;
import com.jphenix.standard.viewhandler.INodeHandler;
import com.jphenix.standard.viewhandler.IViewHandler;

/**
 * 日志类工厂
 * 
 * 2018-07-18 修改了日志输出方法
 * 2018-07-30 增加了从配置文件读取自定义日志文件头信息
 * 2018-09-03 增加了在开发模式下也可以写日志到文件
 * 2018-09-13 简化了整个架构中日志初始化步骤
 * 2019-07-15 增加了自定义日志根路径
 * 2020-08-06 去掉了配置文件接口类，改用实体类
 * 2020-08-20 原来的设置日志编码格式修改为设置控制台日志编码格式和写文件编码格式
 * 2021-03-16 整理了代码格式
 * 2021-09-12 优化了日志配置文件部分
 * 
 * @author 刘虻
 * 2008-8-24上午02:11:36
 */
@ClassInfo({"2021-09-12 18:45","日志类工厂"})
public class FLog {
  
  /**
   * 通过影子类获取日志类
   * @param shadow   影子类
   * @param boss     当前需要输出日志的类
   * @return         日志类
   * 2018年9月13日
   * @author MBG
   */
  public static ILog getLog(ILogShadow shadow,Object boss) {
    if(shadow==null){
      return new SystemOutLog();
    }
    return new XLog(shadow).setBoss(boss);
  }
  
  /**
   * 通过影子类获取日志类
   * @param shadow   影子类
   * @param boss     当前需要输出日志的类
   * @return         日志类
   * 2018年9月13日
   * @author MBG
   */
  @SuppressWarnings("rawtypes")
  public static ILog getLog(ILogShadow shadow,Class boss) {
    return new XLog(shadow).setBoss(boss);
  }

  /**
   * 该方法通常在底层初始化之前使用
   * @param is               配置信息读入流
   * @param configFilePath   配置文件路径
   * @param bf               类加载器
   * @param developMode      是否为开发模式
   * @param prop             参数配置文件信息类
   * @return                 日志影子类
   * 2017年3月10日
   * @author MBG
   */
  public static ILogShadow getLogShadow(
    InputStream  is,
    String       configFilePath,
    IBeanFactory bf,
    boolean      developMode,
    XmlConfProp  prop) {
    try {
      //构建xml解析类
      INodeHandler xml = FNodeHandler.newNodeHandler();
      xml.setXmlStyle(true);
      xml.setStream(is,configFilePath);
      //获取日志配置信息段
      IViewHandler logXml = xml.getFirstChildNodeByNodeName("log");
      if(logXml.isEmpty()) {
        return null;
      }
      //构建新的影子类
      XLogFilter logShadow = new XLogFilter();
      logShadow.setBeanFactory(bf);
      //获取如果是开发模式，是否也按照这个配置文件加载。如果为false，
      //在开发模式下，只将全部日志输出到控制台，不会写入文件
      boolean developUsed = SBoolean.valueOf(prop.getFixParameter(logXml.a("developused")));
      //是否在开发模式下也要写日志到文件
      boolean writeLogFile = SBoolean.valueOf(prop.getParameter("write_log_file"));
      String encoding = null; // 编码格式
      if(developMode && !developUsed && !writeLogFile) {
        //开发模式，并且标记在开发模式中不使用该配置文件
        logShadow.setOutStart(true);
        logShadow.setOutLog(true);
        logShadow.setOutWarning(true);
        logShadow.setOutError(true);
        logShadow.setOutInfo(true);
        logShadow.setOutSql(true);
        logShadow.setOutData(true);
        logShadow.setOutRuntime(true);
        logShadow.setOutSystemLog(true);
        logShadow.setOutSystemError(true);
        logShadow.setOutTLog(true);
        logShadow.setWriteStart(false);
        logShadow.setWriteLog(false);
        logShadow.setWriteWarning(false);
        logShadow.setWriteError(false);
        logShadow.setWriteInfo(false);
        logShadow.setWriteSql(false);
        logShadow.setWriteRuntime(false);
        logShadow.setWriteSystemLog(false);
        logShadow.setWriteSystemError(false);
        logShadow.setWriteDebug(false);
        logShadow.setWriteData(false);
        logShadow.setWriteTLog(false);
      } else {
        String methodName = null; //方法名
        //获取参数信息组
        List<IViewHandler> xmls = xml.getChildNodesByNodeName("property");
        boolean enabled;
        for(IViewHandler pXml:xmls) {
          methodName = pXml.a("name");
          enabled = SBoolean.valueOf(prop.getFixParameter(pXml.getFirstChildNodeByNodeName("boolean").nt()));
          if("setOutStart".equals(methodName)) {
            logShadow.setOutStart(enabled);
          }else if("setOutLog".equals(methodName)) {
            logShadow.setOutLog(enabled);
          }else if("setOutWarning".equals(methodName)) {
            logShadow.setOutWarning(enabled);
          }else if("setOutError".equals(methodName)) {
            logShadow.setOutError(enabled);
          }else if("setOutInfo".equals(methodName)) {
            logShadow.setOutInfo(enabled);
          }else if("setOutSql".equals(methodName)) {
            logShadow.setOutSql(enabled);
          }else if("setOutData".equals(methodName)) {
            logShadow.setOutData(enabled);
          }else if("setOutTLog".equals(methodName)) {
            logShadow.setOutTLog(enabled);
          }else if("setOutRuntime".equals(methodName)) {
            logShadow.setOutRuntime(enabled);
          }else if("setOutSystemLog".equals(methodName)) {
            logShadow.setOutSystemLog(enabled);
          }else if("setOutSystemError".equals(methodName)) {
            logShadow.setOutSystemError(enabled);
          }else if("setWriteStart".equals(methodName)) {
            logShadow.setWriteStart(enabled);
          }else if("setWriteLog".equals(methodName)) {
            logShadow.setWriteLog(enabled);
          }else if("setWriteWarning".equals(methodName)) {
            logShadow.setWriteWarning(enabled);
          }else if("setWriteError".equals(methodName)) {
            logShadow.setWriteError(enabled);
          }else if("setWriteInfo".equals(methodName)) {
            logShadow.setWriteInfo(enabled);
          }else if("setWriteDebug".equals(methodName)) {
            logShadow.setWriteDebug(enabled);
          }else if("setWriteSql".equals(methodName)) {
            logShadow.setWriteSql(enabled);
          }else if("setWriteData".equals(methodName)) {
            logShadow.setWriteData(enabled);
          }else if("setWriteTLog".equals(methodName)) {
            logShadow.setWriteTLog(enabled);
          }else if("setWriteRuntime".equals(methodName)) {
            logShadow.setWriteRuntime(enabled);
          }else if("setWriteSystemLog".equals(methodName)) {
            logShadow.setWriteSystemLog(enabled);
          }else if("setWriteSystemError".equals(methodName)) {
            logShadow.setWriteSystemError(enabled);
          }else if("setConsoleEncoding".equals(methodName)) {
            encoding = prop.getFixParameter(pXml.getFirstChildNodeByNodeName("String").nt());
            if(encoding!=null && encoding.length()>0) {
              logShadow.setConsoleEncoding(encoding);
            }
          }else if("setFileEncoding".equals(methodName)) {
            encoding = prop.getFixParameter(pXml.getFirstChildNodeByNodeName("String").nt());
            if(encoding!=null && encoding.length()>0) {
              logShadow.setFileEncoding(encoding);
            }
          }else if("addCustomLogFileKeys".equals(methodName)) {
            logShadow.addCustomLogFileKeys(prop.getFixParameter(pXml.getFirstChildNodeByNodeName("String").nt()));
          }else if("setFilePath".equals(methodName)) {
            logShadow.setFilePath(
              SFilesUtil.getAllFilePath(
                prop.getParameter("file_sources")+prop.getFixParameter(pXml.getFirstChildNodeByNodeName("Path").nt()),
                bf.getWebInfPath()));
          }
        }
      }
      logShadow.init(); //执行初始化
      return logShadow;
    }catch(Exception e) {
    	e.printStackTrace();
      return new NullLogShadow();
    }
  }

  /**
   * 该方法通常在底层初始化之前使用
   * 
   * 获取当前日志类
   * @param configFilePath 配置文件全路径
   * @param bf             类加载器
   * @param developMode    是否为开发模式
   * @param prop           参数配置文件信息类
   * @author 刘虻
   * 2008-8-24上午02:16:55
   * @return 当前日志类
   */
  public static ILogShadow getLogShadow(
    String       configFilePath,
    IBeanFactory bf,
    boolean      developMode,
    XmlConfProp  prop) {
    try {
      return getLogShadow(
        SFilesUtil.getFileInputStreamByUrl(configFilePath,null),
        configFilePath,
        bf,
        developMode,
        prop);
    }catch(Exception e) {
    	e.printStackTrace();
      return new NullLogShadow();
    }
  }
}
